import { useState, useMemo, useRef, useEffect } from 'react';
// serveFn - 请求函数
// options
// - defaultQuery - 立即执行的请求参数
// - immediate 是否立即执行
// - onSuccess 请求成功的回调函数，可返回一个promise
// - onError 请求异常的回调函数，同理与onSuccess
// - runRule 执行请求函数的规则
export const useRequest = (serveFn, options) => {
  const { onSuccess, onError, defaultQuery, immediate, runRule } =
    options || {};
  const { current: initialQuery } = useRef(
    typeof defaultQuery === 'function' ? defaultQuery() : defaultQuery || null
  );
  const [query, setQuery] = useState(initialQuery);
  const [loading, setLoading] = useState(false);
  const [status, setStatus] = useState('');
  const [data, setData] = useState();
  const { current: serveFnRef } = useRef(serveFn);
  const { current: onSuccessRef } = useRef(onSuccess);
  const { current: onErrorRef } = useRef(onError);
  const { current: runRuleRef } = useRef(runRule);
  const { current: immediateRef } = useRef(immediate || false);
  const isUnmount = useRef(false);
  const actions = useMemo(() => {
    const run = async params => {
      setLoading(true);
      setStatus('pending');
      try {
        const ret = await serveFnRef(params);
        if (isUnmount.current) return;
        const formatRet = await Promise.resolve(
          typeof onSuccessRef === 'function' ? onSuccessRef(ret) : ret
        );
        setData(formatRet);
        setStatus('resolve');
        setLoading(false);
        return Promise.resolve(formatRet);
      } catch (error) {
        if (isUnmount.current) return;
        const formatError = await Promise.resolve(
          typeof onErrorRef === 'function' ? onErrorRef(error) : error
        );
        setStatus('reject');
        setLoading(false);
        return Promise.reject(formatError);
      }
    };
    return {
      run,
    };
  }, [onErrorRef, onSuccessRef, serveFnRef]);

  useEffect(() => {
    isUnmount.current = false;
    if (immediateRef) {
      if (runRuleRef) {
        runRuleRef(query) && actions.run(query);
      } else {
        actions.run(query);
      }
    }
  }, [actions, immediateRef, query, runRuleRef]);

  useEffect(() => {
    return () => {
      isUnmount.current = true;
    };
  }, []);

  return {
    query,
    setQuery,
    loading,
    status,
    data,
    ...actions,
  };
};
